﻿using AutoMapper;

using System;
using System.Linq;
using System.Reflection;

namespace Holla.Infrastructure.AutoMapper
{
    public abstract class AutoMapperProfileBase : Profile
    {
        private readonly Assembly _applicationAssembly;

        protected AutoMapperProfileBase(Assembly applicationAssembly)
        {
            _applicationAssembly = applicationAssembly;

            LoadStandardMappings();
            LoadCustomMappings();
            LoadConverters();
        }

        private void LoadConverters()
        {
        }

        private void LoadStandardMappings()
        {
            var types = _applicationAssembly.GetExportedTypes();
            var mappings =
                from type in types
                from instance in type.GetInterfaces()
                where instance.IsGenericType
                    && instance.GetGenericTypeDefinition() == typeof(IMapFrom<>)
                    && !type.IsAbstract
                    && !type.IsInterface
                select new
                {
                    Source = type.GetInterfaces()[0].GetGenericArguments()[0],
                    Destination = type
                };

            foreach (var mapping in mappings)
            {
                CreateMap(mapping.Source, mapping.Destination).ReverseMap();
            }
        }

        private void LoadCustomMappings()
        {
            var types = _applicationAssembly.GetExportedTypes();

            var mappings =
                from type in types
                from instance in type.GetInterfaces()
                where typeof(IHaveCustomMapping).IsAssignableFrom(type)
                    && !type.IsAbstract
                    && !type.IsInterface
                select (IHaveCustomMapping)Activator.CreateInstance(type);

            foreach (var mapping in mappings)
            {
                mapping.CreateMapping(this);
            }
        }
    }
}